package com.tjakus.quartz;

import java.sql.Timestamp;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import com.tjakus.hibernate.Advertisement;
import com.tjakus.hibernate.HibernateUtil;
import com.tjakus.hibernate.JobTimestamp;
import com.tjakus.hibernate.Services;
import com.tjakus.logging.Logging;
import com.tjakus.parser.XMLManager;
import com.tjakus.webpage.WebpageDownloader;

/**
 * This class represents quartz job which is responsible for reading web pages
 * and update database with new advertisement data.
 * 
 * @author tjakus
 * 
 */

public class GetPageJob implements Job {

	/**
	 * This method executes quartz job which is responsible for adding
	 * advertisement data into database.
	 * 
	 */
	public void execute(JobExecutionContext context) throws JobExecutionException {

		Logging.getLogger().info("GetPageJob - execute [ STARTED ]");
		JobTimestamp jobTimestamp = new JobTimestamp();
		Date date = new Date();
		// Create current time stamp
		Timestamp newTimestamp = new Timestamp(date.getTime());
		Logging.getLogger().debug(
				"GetPageJob - execute - newTimeStamp - [ " + newTimestamp.getTime()
						+ " ]");
		// Get the old time stamp from DB
		Timestamp oldTimestamp = HibernateUtil.getLatestTimestamp();
		// Get all services and URLs from database
		List<Services> services = HibernateUtil.getAllServices();
		// If there is at least one web page parse web page and update table
		if (services.iterator().hasNext()) {
			for (Iterator<Services> iter = services.iterator(); iter.hasNext();) {
				Services service = iter.next();
				this.addNewAdvertisements(newTimestamp, oldTimestamp, service);
			}
		}

		// Update time stamp in JobTimestamp table with latest one
		jobTimestamp.setLastTimestamp(newTimestamp);
		HibernateUtil.deleteLatestTimestamp();
		HibernateUtil.updateLatestTimestamp(jobTimestamp);
		Logging.getLogger().info("GetPageJob - execute [ FINISHED ]");
	}

	/**
	 * This method adds advertisement data into database.
	 * 
	 */
	private void addNewAdvertisements(Timestamp newTimestamp,
			Timestamp oldTimestamp, Services service) {

		Advertisement newAdvertisement = new Advertisement();
		Advertisement oldAdvertisement = null;
		String htmlPage = "";
		WebpageDownloader webpage = new WebpageDownloader();
		htmlPage = webpage.retrieveAndGetHtmlPage(service.getUrl());
		if (htmlPage == null) {
			Logging.getLogger().error(
					"GetPageJob - addNewAdvertisements - UNABLE to fetch WEB page: [ "
							+ service.getUrl() + " ]");
			return;
		}
		// Fix for web page which has some fake date after id="filter_content"
		int index = htmlPage.indexOf("id=\"filter_content\"");
		if (index > 0) {
			htmlPage = htmlPage.substring(0, index);
		}
		
		// Create small XML files to get advertisement data from web page
		String str = "";
		int indexOfSubstring1 = 0;
		int indexOfSubstring2 = 0;

		while (indexOfSubstring1 != -1) {
			String someString1 = "<span class=\"item_wrap\">";
			String someString2 = "</li>";
			indexOfSubstring1 = htmlPage.indexOf(someString1, indexOfSubstring2);
			indexOfSubstring2 = htmlPage.indexOf(someString2, indexOfSubstring1 + 20);

			str = htmlPage.substring(indexOfSubstring1, indexOfSubstring2);
			newAdvertisement = XMLManager.getAdvertisementData(str);

			if (!(newAdvertisement == null)) {
				newAdvertisement.setServiceId(service.getServiceId());
				newAdvertisement.setTimestamp(newTimestamp);

				// If there is no advertisement URL in DB then add it
				oldAdvertisement = HibernateUtil.getAdvertisementByUrl(newAdvertisement
						.getUrl());
				if (oldAdvertisement == null) {
					Logging
							.getLogger()
							.info(
									"GetPageJob - addNewAdvertisements - [ New advertisement added ]");
					HibernateUtil.addAdvetisement(newAdvertisement);
				}
			}
			if (indexOfSubstring1 == htmlPage.lastIndexOf(someString1))
				break;
		}
	}
}
